﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
using System.Configuration;

class HTMLTable
{
    #region single element
    static public HtmlGenericControl mk_cell(String contents)
    {
        HtmlGenericControl c = new HtmlGenericControl();
        c.TagName = "td";
        c.InnerText = contents;
        return c;
    }

    static public HtmlGenericControl mk_row(HtmlGenericControl cell)
    {
        HtmlGenericControl r = new HtmlGenericControl();
        r.TagName = "tr";
        r.Controls.Add(cell);
        return r;
    }

    static public HtmlGenericControl mk_table(HtmlGenericControl row)
    {
        HtmlGenericControl t = new HtmlGenericControl();
        t.TagName = "table";
        t.Controls.Add(row);
        return t;
    }

    #endregion

    #region array elements
    static public HtmlGenericControl mk_cell(HtmlGenericControl contents)
    {
        HtmlGenericControl c = new HtmlGenericControl();
        c.TagName = "td";
        c.Controls.Add(contents);
        return c;
    }

    static public HtmlGenericControl mk_row(HtmlGenericControl[] cells)
    {
        HtmlGenericControl r = new HtmlGenericControl ();
        r.TagName = "tr";        
        foreach (HtmlGenericControl c in cells)
        {
            r.Controls.Add(c);
        }
        return r;
    }

    static public HtmlGenericControl mk_table(HtmlGenericControl[] rows)
    {
        HtmlGenericControl t = new HtmlGenericControl();
        t.TagName = "table";        
        foreach (HtmlGenericControl c in rows)
        {
            t.Controls.Add(c);
        }
        return t;
    }
    #endregion
}

public partial class Talk : System.Web.UI.Page
{
    static readonly Int32 INVALIDID = -1;
    class PostRecord
    {
        public String Poster = "";
        public String Acceptor = "";
        public String Body = "";
        public Int32 ReplyWhich = INVALIDID; // 指向 ID
        public Int32 SubjectID = INVALIDID; // 指向 ID
        public DateTime PostTime = DateTime.MinValue;
        public Int32 ID ; //自增长的
    }

    void display_history_talk()
    {
        panel_subjects.Controls.Clear();
        List<PostRecord> subjects = Get_subjects();
        if (subjects.Count <= 0)
            return;

        foreach (PostRecord r in subjects)
        {
            List<PostRecord> reply_posts = Get_reply(r.ID);
            Control subject = display_post(r);

            List<HtmlGenericControl> reply_controls = new List<HtmlGenericControl>();
            if (reply_posts != null && reply_posts.Count > 0)
            {
                foreach (PostRecord re in reply_posts)
                {
                    HtmlGenericControl reply_control = display_post(re);
                    reply_control = coat_with("ul", reply_control);
                    reply_controls.Add(reply_control);
                }
            }
            else if (isadmin)
            {
                // 显示编辑框与回复按钮
                HtmlGenericControl editrow =  make_reply_row_for_not_replied_post(r.ID);
                editrow = coat_with("ul", editrow);
                reply_controls.Add(editrow);
            }

          

            Control line = coat_ul(subject);
            foreach (Control c in reply_controls)
            {
                Control t = coat_with("ul", c);
                line.Controls.Add(t);
            }

            panel_subjects.Controls.Add(line);       
            HtmlGenericControl hr = new HtmlGenericControl();
            hr.TagName = "hr";
            hr.Attributes["width"] = "46%";
            hr.Attributes["align"] = "left";
            hr.Attributes["style"] = "background-color:black";            
            panel_subjects.Controls.Add(hr);
        }
          
    }

    public bool isadmin = false;

    protected void Page_Load(object sender, EventArgs e)
    {
        isadmin = ConfigurationManager.AppSettings["IsAuthenticated"] == "true";
        display_history_talk();
    }

    bool isPostReplied(Int32 sid)
    {
        String select = "";
        try
        {
            select = "SELECT ID FROM Talks WHERE SubjectID = {0}"; // the reply of the subject
            select = String.Format(select, sid.ToString() );
            SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer1"].ConnectionString);
            SqlCommand cmd = new SqlCommand(select, conn);
            conn.Open();
            SqlDataReader reader = cmd.ExecuteReader();
            bool replied = false;
            if (reader.HasRows)
            {
                replied = true;
            }
            reader.Close();
            conn.Close();
            return replied;
        }
        catch (Exception e)
        {
            String msg = String.Format("数据库访问失败, 连接串={0}, sql语句={1}!",
                                        ConfigurationManager.ConnectionStrings["LocalSqlServer1"].ConnectionString, select);
            ShowAlertMessage(msg);
        }
        return false;
    }

    HtmlGenericControl display_post(PostRecord rec) // return a table 
    {        
        HtmlGenericControl user = new HtmlGenericControl();
        user = coat_div(user);
        user.InnerText = rec.Poster;

        HtmlGenericControl time = new HtmlGenericControl();
        time = coat_div(time);
        time.InnerText = rec.PostTime.ToString();


        HtmlGenericControl cell = new HtmlGenericControl();
        cell.TagName = "td";
        cell.Controls.Add(user);
        cell.Controls.Add(time);

        HtmlGenericControl cell_01 = new HtmlGenericControl();
        cell_01.TagName = "td";
        TextBox tb = new TextBox();
        tb.TextMode = TextBoxMode.MultiLine;
        tb.Text = rec.Body;
        tb.Enabled = false;
        tb.Height = 50;
        tb.Width = 600;
        tb.MaxLength = 2048;
        cell_01.Controls.Add(tb);

        HtmlGenericControl row_0 = new HtmlGenericControl();
        row_0.TagName = "tr";
        row_0.Controls.Add(cell);
        row_0.Controls.Add(cell_01);
        HtmlGenericControl table = new HtmlGenericControl();
        table.TagName = "table";
        table.Controls.Add(row_0);
        return table;
    }
    protected void OnClick_reply(object sender, EventArgs e)
    {
        try
        {
            Button btn_re = sender as Button;
            String name = btn_re.ID;
           // String[] parts = name.Split('_');
            List<String> li = new List<string>(name.Split('_'));
            
            Int32 id = Int32.Parse(li[li.Count - 1]);
            String tb_idname = "text_" + "reply_" + id.ToString();

            TextBox tb = Page.FindControl(tb_idname) as TextBox;
            PostRecord r = new PostRecord();
            r.Poster = "admin";
            //r.Acceptor = ""; // should fetch from DB. 一问一答就没必要了
            r.Body = tb.Text.Trim();
            //r.ReplyWhich = id;// 目前没用，当做到一问多答，可相互回复时，该项就有用了。
            r.SubjectID = id;
            r.PostTime = System.DateTime.Now;

            // insert to db
            String insert = "INSERT INTO Talks (Poster, Body, SubjectID, PostTime) values( '{0}', '{1}','{2}','{3}')";
            insert = String.Format(insert, r.Poster, r.Body, r.SubjectID, r.PostTime);
            exec_sql(insert);
            display_history_talk();
        }
        catch (Exception err)
        {
            ShowAlertMessage("回复失败! " + err.ToString());
        }

    }

    private HtmlGenericControl make_reply_row_for_not_replied_post(Int32 subjectID) // return <tr> control
    {
        if (!isadmin)
            return null;

        Button btn = new Button();
        string strid = subjectID.ToString();

        btn.ID = "btn_reply_" + strid; //格式固定
        btn.Text = "回复";
        btn.Click += OnClick_reply;

        TextBox tb = new TextBox();
        tb.ID = "text_reply_" + strid; // 格式固定
        tb.TextMode = TextBoxMode.MultiLine;
      //  tb.Text = "请输入回复内容...";
        tb.Enabled = true;
        tb.Width = 600;
        tb.Height = 50;

        HtmlGenericControl tr = new HtmlGenericControl();
        tr.TagName = "tr";
        HtmlGenericControl td00 = new HtmlGenericControl();
        td00.TagName = "td";

        HtmlGenericControl td01= new HtmlGenericControl();
        td01.TagName = "td";

        td01.Controls.Add(tb); 
        td01.Controls.Add(btn);        
        tr.Controls.Add(td00);
        tr.Controls.Add(td01);
        return tr;
    }


    private HtmlGenericControl make_reply_row_for_replied_post(Int32 subjectID) // return <tr> control
    {
        string strid = subjectID.ToString();
        TextBox tb = new TextBox();
        tb.ID = "text_reply_" + strid; // 格式固定
        tb.TextMode = TextBoxMode.MultiLine;        
        tb.Enabled = false;
        tb.Width = 600;
        tb.Height = 50;

        HtmlGenericControl tr = new HtmlGenericControl();
        tr.TagName = "tr";
        HtmlGenericControl td00 = new HtmlGenericControl();
        td00.TagName = "td";

        HtmlGenericControl td01 = new HtmlGenericControl();
        td01.TagName = "td";

        td01.Controls.Add(tb);        
        tr.Controls.Add(td00);
        tr.Controls.Add(td01);
        return tr;
    }

    protected void OnClick_btn_post(object sender, EventArgs e)
    {
        PostRecord newrec = new PostRecord();
        String name = text_poster_name.Text.Trim();
        String email = text_poster_email.Text.Trim();
        if (name.Length > 0  && email.Length > 0)
        {
            name = name + "(" + email + ")";
        }
        else
        {
            name = name + email;
        }
        if (name.Length == 0)
        {
            newrec.Poster = "匿名" + Request.ServerVariables["REMOTE_ADDR"];
        }
        newrec.Poster = name;
        newrec.PostTime = System.DateTime.Now;
        newrec.Acceptor = "";
        newrec.Body = text_post.Text.Trim();
        if (newrec.Body.Length <= 0)
        {
            ShowAlertMessage("请留下文字后再提交……");
            return;
        }
        newrec.SubjectID = -1; // itself is subject
        String insert = "INSERT INTO Talks (Poster, Body, SubjectID, PostTime) values( '{0}', '{1}','{2}','{3}')";
        insert = String.Format(insert, newrec.Poster, newrec.Body, newrec.SubjectID, newrec.PostTime);
        if (exec_sql(insert))
        {
            display_history_talk();
        }

        text_poster_name.Text = "";
        text_poster_email.Text = "";
        text_post.Text = "";

    }

    bool exec_sql(String sql)
    {
        // save to db
        String insert = sql;
        SqlTransaction trans = null;
        SqlConnection conn = null;
        try
        {
            conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer1"].ConnectionString);
            conn.Open();
            trans = conn.BeginTransaction();
            SqlCommand cmd = new SqlCommand(insert, conn, trans);
            cmd.CommandText = insert;
            cmd.ExecuteNonQuery();
            trans.Commit();
            return true;
        }
        catch (Exception err)
        {
            ShowAlertMessage(err.ToString());
            if (trans != null)
            {
                trans.Rollback();
            }
            return false;
        }
    }

    List<PostRecord> Get_subjects()
    {
        String select = "";
        try
        {
            select = "SELECT distinct Poster, Acceptor,  Body, ReplyWhich, PostTime, ID FROM Talks WHERE SubjectID < 0 order by PostTime Desc"; // all subjects
            SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer1"].ConnectionString);
            SqlCommand cmd = new SqlCommand(select, conn);
            conn.Open();
            SqlDataReader reader = cmd.ExecuteReader();            
            List<PostRecord> subs = new List<PostRecord>();
            while (reader.Read())
            {
                PostRecord rec  = new PostRecord();
                rec.Poster = reader.GetValue(0) as String;
                rec.Acceptor = reader.GetValue(1) as String;
                rec.Body = reader.GetValue(2) as String;
                try
                {
                    rec.ReplyWhich = Int32.Parse(reader.GetValue(3).ToString());
                }
                catch (Exception)
                {
                    rec.ReplyWhich = INVALIDID;
                }
                rec.PostTime = DateTime.Parse(reader.GetValue(4).ToString());
                rec.ID = Int32.Parse(reader.GetValue(5).ToString());
                subs.Add(rec);
            }
            reader.Close();
            conn.Close();
            return subs;         
        }
        catch (Exception e)
        {
            String msg = String.Format("数据库访问失败, 连接串={0}, sql语句={1}!",
                                        ConfigurationManager.ConnectionStrings["LocalSqlServer1"].ConnectionString, select);
            ShowAlertMessage(msg);
        }
        return null;
    }

    List<PostRecord> Get_reply(Int32 subjectID)
    {
        // 获取对　该　subject的回复
        String select = "";
        try
        {
            select = "SELECT Poster, Acceptor,  Body, ReplyWhich, PostTime, ID FROM Talks WHERE SubjectID = {0} order by PostTime Desc"; // all replies
            select = String.Format(select, subjectID);
            SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer1"].ConnectionString);
            SqlCommand cmd = new SqlCommand(select, conn);
            conn.Open();
            SqlDataReader reader = cmd.ExecuteReader();
            List<PostRecord> replies = new List<PostRecord>();
            while (reader.Read())
            {
                PostRecord rec = new PostRecord();
                rec.Poster = reader.GetValue(0) as String;
                rec.Acceptor = reader.GetValue(1) as String;
                rec.Body = reader.GetValue(2) as String;
                try
                {
                    rec.ReplyWhich = Int32.Parse(reader.GetValue(3).ToString());
                }
                catch (Exception)
                {
                    rec.ReplyWhich = INVALIDID;
                }
                rec.PostTime = DateTime.Parse(reader.GetValue(4).ToString());
                rec.ID = Int32.Parse(reader.GetValue(5).ToString());
                replies.Add(rec);
            }
            reader.Close();
            conn.Close();
            return replies;
        }
        catch (Exception e)
        {
            String msg = String.Format("数据库访问失败, 连接串={0}, sql语句={1}!",
                                        ConfigurationManager.ConnectionStrings["LocalSqlServer1"].ConnectionString, select);
            ShowAlertMessage(msg);
        }
        return null;
    }

    private void ShowAlertMessage(string message)
    {
        Page page = HttpContext.Current.Handler as Page;

        if (page != null)
        {
            // message = message.Replace("'", "\'");
            //ScriptManager.RegisterStartupScript(page, page.GetType(), "err_msg", "alert('" + message + "');", true);
        }
    }

    private HtmlGenericControl coat_div(Control subdiv)
    {
        HtmlGenericControl div = new HtmlGenericControl();
        div.TagName = "div";
        div.Controls.Add(subdiv);
        return div;
    }

    private HtmlGenericControl coat_ul(Control subdiv)
    {
        HtmlGenericControl div = new HtmlGenericControl();
        div.TagName = "ul";
        div.Controls.Add(subdiv);
        return div;
    }

    private HtmlGenericControl coat_with(String type, Control subdiv)
    {
        HtmlGenericControl div = new HtmlGenericControl();
        div.TagName = type;
        div.Controls.Add(subdiv);
        return div;
    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        this.Server.Transfer("~/default.aspx");
    }
}